﻿using Newtonsoft.Json.Converters;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Framework.Core.Helper
{
	public class JsonHelper
	{
		public static string ObjToStr<T>(T obj, string dateTimeFormat)
		{
			IsoDateTimeConverter timeConverter = new IsoDateTimeConverter()
			{
				DateTimeFormat = dateTimeFormat
			};
			return JsonConvert.SerializeObject(obj, Formatting.Indented, timeConverter);
		}

		public static string ObjToStr<T>(T obj)
		{
			return JsonConvert.SerializeObject(obj);
		}

		public static T StrToObj<T>(string str)
		{
			return JsonConvert.DeserializeObject<T>(str)!;
		}
		/// <summary>
		/// 转换对象为JSON格式数据
		/// </summary>
		/// <typeparam name="T">类</typeparam>
		/// <param name="obj">对象</param>
		/// <returns>字符格式的JSON数据</returns>
		public static string GetJSON<T>(object obj)
		{
			string result = string.Empty;
			try
			{
				System.Runtime.Serialization.Json.DataContractJsonSerializer serializer =
				new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(T));
				using (MemoryStream ms = new MemoryStream())
				{
					serializer.WriteObject(ms, obj);
					result = Encoding.UTF8.GetString(ms.ToArray());
				}
			}
			catch (Exception)
			{
				throw;
			}
			return result;
		}
		/// <summary>
		/// 转换List<T>的数据为JSON格式
		/// </summary>
		/// <typeparam name="T">类</typeparam>
		/// <param name="vals">列表值</param>
		/// <returns>JSON格式数据</returns>
		public string JSON<T>(List<T> vals)
		{
			StringBuilder st = new StringBuilder();
			try
			{
				System.Runtime.Serialization.Json.DataContractJsonSerializer s = new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(T));

				foreach (T city in vals)
				{
					using (MemoryStream ms = new MemoryStream())
					{
						s.WriteObject(ms, city);
						st.Append(Encoding.UTF8.GetString(ms.ToArray()));
					}
				}
			}
			catch (Exception)
			{
			}

			return st.ToString();
		}
		/// <summary>
		/// JSON格式字符转换为T类型的对象
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="jsonStr"></param>
		/// <returns></returns>
		public static T ParseFormByJson<T>(string jsonStr)
		{
			T obj = Activator.CreateInstance<T>();
			using (MemoryStream ms =
			new MemoryStream(Encoding.UTF8.GetBytes(jsonStr)))
			{
				System.Runtime.Serialization.Json.DataContractJsonSerializer serializer =
				new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(T));
				return (T)serializer.ReadObject(ms)!;
			}
		}

		public string JSON1<SendData>(List<SendData> vals)
		{
			StringBuilder st = new StringBuilder();
			try
			{
				System.Runtime.Serialization.Json.DataContractJsonSerializer s = new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(SendData));

				foreach (SendData city in vals)
				{
					using (MemoryStream ms = new MemoryStream())
					{
						s.WriteObject(ms, city);
						st.Append(Encoding.UTF8.GetString(ms.ToArray()));
					}
				}
			}
			catch (Exception)
			{
			}

			return st.ToString();
		}

		private static bool IsJsonStart(ref string json)
		{
			if (!string.IsNullOrEmpty(json))
			{
				json = json.Trim('\r', '\n', ' ');
				if (json.Length > 1)
				{
					char s = json[0];
					char e = json[json.Length - 1];
					return s == '{' && e == '}' || s == '[' && e == ']';
				}
			}
			return false;
		}
		public static bool IsJson(string json)
		{
			int errIndex;
			return IsJson(json, out errIndex);
		}
		public static bool IsJson(string json, out int errIndex)
		{
			errIndex = 0;
			if (IsJsonStart(ref json))
			{
				CharState cs = new CharState();
				char c;
				for (int i = 0; i < json.Length; i++)
				{
					c = json[i];
					if (SetCharState(c, ref cs) && cs.childrenStart)//设置关键符号状态。
					{
						string item = json.Substring(i);
						int err;
						int length = GetValueLength(item, true, out err);
						cs.childrenStart = false;
						if (err > 0)
						{
							errIndex = i + err;
							return false;
						}
						i = i + length - 1;
					}
					if (cs.isError)
					{
						errIndex = i;
						return false;
					}
				}

				return !cs.arrayStart && !cs.jsonStart;
			}
			return false;
		}

		/// <summary>
		/// 获取值的长度（当Json值嵌套以"{"或"["开头时）
		/// </summary>
		private static int GetValueLength(string json, bool breakOnErr, out int errIndex)
		{
			errIndex = 0;
			int len = 0;
			if (!string.IsNullOrEmpty(json))
			{
				CharState cs = new CharState();
				char c;
				for (int i = 0; i < json.Length; i++)
				{
					c = json[i];
					if (!SetCharState(c, ref cs))//设置关键符号状态。
					{
						if (!cs.jsonStart && !cs.arrayStart)//json结束，又不是数组，则退出。
						{
							break;
						}
					}
					else if (cs.childrenStart)//正常字符，值状态下。
					{
						int length = GetValueLength(json.Substring(i), breakOnErr, out errIndex);//递归子值，返回一个长度。。。
						cs.childrenStart = false;
						cs.valueStart = 0;
						//cs.state = 0;
						i = i + length - 1;
					}
					if (breakOnErr && cs.isError)
					{
						errIndex = i;
						return i;
					}
					if (!cs.jsonStart && !cs.arrayStart)//记录当前结束位置。
					{
						len = i + 1;//长度比索引+1
						break;
					}
				}
			}
			return len;
		}

		/// <summary>
		/// 设置字符状态(返回true则为关键词，返回false则当为普通字符处理）
		/// </summary>
		private static bool SetCharState(char c, ref CharState cs)
		{
			cs.CheckIsError(c);
			switch (c)
			{
				case '{'://[{ "[{A}]":[{"[{B}]":3,"m":"C"}]}]
					#region 大括号
					if (cs.keyStart <= 0 && cs.valueStart <= 0)
					{
						cs.keyStart = 0;
						cs.valueStart = 0;
						if (cs.jsonStart && cs.state == 1)
						{
							cs.childrenStart = true;
						}
						else
						{
							cs.state = 0;
						}
						cs.jsonStart = true;//开始。
						return true;
					}
					#endregion
					break;
				case '}':
					#region 大括号结束
					if (cs.keyStart <= 0 && cs.valueStart < 2 && cs.jsonStart)
					{
						cs.jsonStart = false;//正常结束。
						cs.state = 0;
						cs.keyStart = 0;
						cs.valueStart = 0;
						cs.setDicValue = true;
						return true;
					}
					// cs.isError = !cs.jsonStart && cs.state == 0;
					#endregion
					break;
				case '[':
					#region 中括号开始
					if (!cs.jsonStart)
					{
						cs.arrayStart = true;
						return true;
					}
					else if (cs.jsonStart && cs.state == 1)
					{
						cs.childrenStart = true;
						return true;
					}
					#endregion
					break;
				case ']':
					#region 中括号结束
					if (cs.arrayStart && !cs.jsonStart && cs.keyStart <= 2 && cs.valueStart <= 0)//[{},333]//这样结束。
					{
						cs.keyStart = 0;
						cs.valueStart = 0;
						cs.arrayStart = false;
						return true;
					}
					#endregion
					break;
				case '"':
				case '\'':
					#region 引号
					if (cs.jsonStart || cs.arrayStart)
					{
						if (cs.state == 0)//key阶段,有可能是数组["aa",{}]
						{
							if (cs.keyStart <= 0)
							{
								cs.keyStart = c == '"' ? 3 : 2;
								return true;
							}
							else if (cs.keyStart == 2 && c == '\'' || cs.keyStart == 3 && c == '"')
							{
								if (!cs.escapeChar)
								{
									cs.keyStart = -1;
									return true;
								}
								else
								{
									cs.escapeChar = false;
								}
							}
						}
						else if (cs.state == 1 && cs.jsonStart)//值阶段必须是Json开始了。
						{
							if (cs.valueStart <= 0)
							{
								cs.valueStart = c == '"' ? 3 : 2;
								return true;
							}
							else if (cs.valueStart == 2 && c == '\'' || cs.valueStart == 3 && c == '"')
							{
								if (!cs.escapeChar)
								{
									cs.valueStart = -1;
									return true;
								}
								else
								{
									cs.escapeChar = false;
								}
							}

						}
					}
					#endregion
					break;
				case ':':
					#region 冒号
					if (cs.jsonStart && cs.keyStart < 2 && cs.valueStart < 2 && cs.state == 0)
					{
						if (cs.keyStart == 1)
						{
							cs.keyStart = -1;
						}
						cs.state = 1;
						return true;
					}
					// cs.isError = !cs.jsonStart || (cs.keyStart < 2 && cs.valueStart < 2 && cs.state == 1);
					#endregion
					break;
				case ',':
					#region 逗号 //["aa",{aa:12,}]

					if (cs.jsonStart)
					{
						if (cs.keyStart < 2 && cs.valueStart < 2 && cs.state == 1)
						{
							cs.state = 0;
							cs.keyStart = 0;
							cs.valueStart = 0;
							//if (cs.valueStart == 1)
							//{
							//    cs.valueStart = 0;
							//}
							cs.setDicValue = true;
							return true;
						}
					}
					else if (cs.arrayStart && cs.keyStart <= 2)
					{
						cs.keyStart = 0;
						//if (cs.keyStart == 1)
						//{
						//    cs.keyStart = -1;
						//}
						return true;
					}
					#endregion
					break;
				case ' ':
				case '\r':
				case '\n'://[ "a",\r\n{} ]
				case '\0':
				case '\t':
					if (cs.keyStart <= 0 && cs.valueStart <= 0) //cs.jsonStart && 
					{
						return true;//跳过空格。
					}
					break;
				default: //值开头。。
					if (c == '\\') //转义符号
					{
						if (cs.escapeChar)
						{
							cs.escapeChar = false;
						}
						else
						{
							cs.escapeChar = true;
							return true;
						}
					}
					else
					{
						cs.escapeChar = false;
					}
					if (cs.jsonStart || cs.arrayStart) // Json 或数组开始了。
					{
						if (cs.keyStart <= 0 && cs.state == 0)
						{
							cs.keyStart = 1;//无引号的
						}
						else if (cs.valueStart <= 0 && cs.state == 1 && cs.jsonStart)//只有Json开始才有值。
						{
							cs.valueStart = 1;//无引号的
						}
					}
					break;
			}
			return false;
		}
	}
	/// <summary>
	/// 字符状态
	/// </summary>
	public class CharState
	{
		internal bool jsonStart = false;//以 "{"开始了...
		internal bool setDicValue = false;// 可以设置字典值了。
		internal bool escapeChar = false;//以"\"转义符号开始了
		/// <summary>
		/// 数组开始【仅第一开头才算】，值嵌套的以【childrenStart】来标识。
		/// </summary>
		internal bool arrayStart = false;//以"[" 符号开始了
		internal bool childrenStart = false;//子级嵌套开始了。
		/// <summary>
		/// 【0 初始状态，或 遇到“,”逗号】；【1 遇到“：”冒号】
		/// </summary>
		internal int state = 0;

		/// <summary>
		/// 【-1 取值结束】【0 未开始】【1 无引号开始】【2 单引号开始】【3 双引号开始】
		/// </summary>
		internal int keyStart = 0;
		/// <summary>
		/// 【-1 取值结束】【0 未开始】【1 无引号开始】【2 单引号开始】【3 双引号开始】
		/// </summary>
		internal int valueStart = 0;
		internal bool isError = false;//是否语法错误。

		internal void CheckIsError(char c)//只当成一级处理（因为GetLength会递归到每一个子项处理）
		{
			if (keyStart > 1 || valueStart > 1)
			{
				return;
			}
			//示例 ["aa",{"bbbb":123,"fff","Ddd"}] 
			switch (c)
			{
				case '{'://[{ "[{A}]":[{"[{B}]":3,"m":"C"}]}]
					isError = jsonStart && state == 0;//重复开始错误 同时不是值处理。
					break;
				case '}':
					isError = !jsonStart || keyStart != 0 && state == 0;//重复结束错误 或者 提前结束{"aa"}。正常的有{}
					break;
				case '[':
					isError = arrayStart && state == 0;//重复开始错误
					break;
				case ']':
					isError = !arrayStart || jsonStart;//重复开始错误 或者 Json 未结束
					break;
				case '"':
				case '\'':
					isError = !(jsonStart || arrayStart); //json 或数组开始。
					if (!isError)
					{
						//重复开始 [""",{"" "}]
						isError = state == 0 && keyStart == -1 || state == 1 && valueStart == -1;
					}
					if (!isError && arrayStart && !jsonStart && c == '\'')//['aa',{}]
					{
						isError = true;
					}
					break;
				case ':':
					isError = !jsonStart || state == 1;//重复出现。
					break;
				case ',':
					isError = !(jsonStart || arrayStart); //json 或数组开始。
					if (!isError)
					{
						if (jsonStart)
						{
							isError = state == 0 || state == 1 && valueStart > 1;//重复出现。
						}
						else if (arrayStart)//["aa,] [,]  [{},{}]
						{
							isError = keyStart == 0 && !setDicValue;
						}
					}
					break;
				case ' ':
				case '\r':
				case '\n'://[ "a",\r\n{} ]
				case '\0':
				case '\t':
					break;
				default: //值开头。。
					isError = !jsonStart && !arrayStart || state == 0 && keyStart == -1 || valueStart == -1 && state == 1;//
					break;
			}
			//if (isError)
			//{

			//}
		}
	}
}
